From 56a7a7851b09cb30a5cd543c8cb4f926109b4290 Mon Sep 17 00:00:00 2001
From: Fuwn <contact@fuwn.net>
Date: Sun, 24 May 2026 13:22:34 +0000
Subject: refactor(locale): move hardcoded UI strings into english locale

Adds optional namespaces (common, errors, commandPalette, headTitle,
notifications, schedule, events, home, reader, routes, badgePreview,
badgeWall) and extends existing ones (settings.*, lists.*, tools.*,
user.*, hololive.*) on the Locale interface. New fields are optional
so japanese.ts can omit them; svelte-i18n's fallbackLocale handles
the runtime miss.

HeadTitle gains an optional routeKey prop for type-safe lookup.
defaultActions becomes a factory so the command palette re-reads
locale on language toggle. The existing JP feedback translation
in routes/settings is preserved via japanese.ts.

Out of scope (kept hardcoded): service-worker.ts, app.html,
Landing*.svelte, tools.ts registry, Easter Event 2025 pages.
---
 src/routes/user/[user]/+page.svelte | 45 +++++++++++++++++++++----------------
 1 file changed, 26 insertions(+), 19 deletions(-)

(limited to 'src/routes/user/[user]/+page.svelte')

diff --git a/src/routes/user/[user]/+page.svelte b/src/routes/user/[user]/+page.svelte
index 1bcedc52..bfcdd87b 100644
--- a/src/routes/user/[user]/+page.svelte
+++ b/src/routes/user/[user]/+page.svelte
@@ -237,27 +237,29 @@ const toggleCategory = () => {
 // 8.5827814569536423841e0
 </script>
 
-<HeadTitle route={`${data.username}'s Profile`} path={`/user/${data.username}`} />
+<HeadTitle
+  route={$locale({ values: { username: data.username } }).headTitle?.userProfile}
+  path={`/user/${data.username}`}
+/>
 
 {#if error}
   <AnimeRateLimited>
-    <a href={`https://anilist.co/user/${data.username}`} target="_blank">@{data.username}</a>'s
-    profile could not be loaded.
+    <a href={`https://anilist.co/user/${data.username}`} target="_blank">@{data.username}</a>{$locale().errors?.profileCouldNotBeLoaded?.split('@{username}')[1]}
   </AnimeRateLimited>
 {:else}
   {#if userData === null}
     <Message slot withReload>
       <p>
-        Could not load user profile for <a
+        {$locale().user.profile.notLoaded?.split('@{username}')[0]}<a
           href={`https://anilist.co/user/${data.username}`}
           target="_blank">@{data.username}</a
-        >.
+        >{$locale().user.profile.notLoaded?.split('@{username}')[1]}
       </p>
     </Message>
   {:else if userData === undefined}
     <Skeleton card={false} bigCard count={1} height="224px" />
 
-    <Message message="Loading user profile ..." />
+    <Message message={$locale().user.profile.loadingProfile} />
   {:else}
     <div class="card card-small">
       <div
@@ -297,10 +299,10 @@ const toggleCategory = () => {
               </a>
               {#if userData && authorisedUsers.includes(userData.id)}
                 &#8204;
-                <button class="unclickable-button button-badge badge-rainbow">Owner</button>
+                <button class="unclickable-button button-badge badge-rainbow">{$locale().user.profile.owner}</button>
               {/if}
               <span class="click-item separator opaque">•</span>
-              <a href={root(`/user/${userData.name}/badges`)}>Badge Wall</a>
+              <a href={root(`/user/${userData.name}/badges`)}>{$locale().user.profile.badgeWallLink}</a>
             </p>
 
             {#if preferences && preferences.biography && preferences.biography.length > 0}
@@ -362,7 +364,7 @@ const toggleCategory = () => {
             >
               <a href={root(`/hololive/${encodeURIComponent(stream)}`)}>
                 <div class="user-grid-hololive-badges">
-                  <ParallaxImage source={avatar} alternativeText="Avatar" />
+                  <ParallaxImage source={avatar} alternativeText={$locale().navigation.avatar ?? 'Avatar'} />
                 </div>
               </a>
             </LinkedTooltip>
@@ -401,7 +403,7 @@ const toggleCategory = () => {
 
       <Spacer />
 
-      Pinned Categories
+      {$locale().user.profile.pinnedCategories}
 
       <div class="pinned-categories">
         {#each ownerPreferences.pinned_badge_wall_categories as category}
@@ -423,23 +425,28 @@ const toggleCategory = () => {
             <button
               onclick={() => {
                 if (userData) toggleCategoryQuery.mutate({ category }).then();
-              }}>Remove</button
+              }}>{$locale().common?.remove}</button
             >
           </div>
         {/each}
 
         <span class="card card-small pinned-category">
           <span class="pinned-category-name">
-            <input type="text" id="category" placeholder="Category" style="width: 10em;" />
+            <input
+              type="text"
+              id="category"
+              placeholder={$locale().user.profile.categoryPlaceholder}
+              style="width: 10em;"
+            />
           </span>
 
-          <button class="button-lined" onclick={toggleCategory}>Add</button>
+          <button class="button-lined" onclick={toggleCategory}>{$locale().common?.add}</button>
         </span>
       </div>
 
       <Spacer />
 
-      Biography
+      {$locale().user.profile.biography}
 
       <button
         onclick={() => {
@@ -449,19 +456,19 @@ const toggleCategory = () => {
                 biography: getBiography()
               })
               .then();
-        }}>Save</button
+        }}>{$locale().common?.save}</button
       >
       <textarea
         value={ownerPreferences.biography}
         rows="5"
         cols="100"
         id="biography"
-        placeholder="Markdown supported!"
+        placeholder={$locale().user.profile.markdownPlaceholder}
       ></textarea>
 
       <Spacer />
 
-      Badge Wall Custom CSS
+      {$locale().user.profile.badgeWallCustomCss}
 
       <button
         onclick={() => {
@@ -471,14 +478,14 @@ const toggleCategory = () => {
                 css: getBadgeWallCSS()
               })
               .then();
-        }}>Save</button
+        }}>{$locale().common?.save}</button
       >
       <textarea
         value={ownerPreferences.badge_wall_css}
         rows="10"
         cols="100"
         id="badgeWallCSS"
-        placeholder="/* Use classes and IDs such as .badges, #badges, .badge, or standard elements like body and details, or anything, as long as it's valid CSS! */"
+        placeholder={$locale().user.profile.customCssPlaceholder}
       ></textarea>
     </details>
   {/if}
-- 
cgit v1.2.3

